package cc.rengu.igas.channel.ncqs.core.service.trans;


import cc.rengu.igas.channel.ncqs.common.constant.NcqsConfigConstant;
import cc.rengu.igas.channel.ncqs.common.constant.NcqsParamConstant;
import cc.rengu.igas.channel.ncqs.common.constant.NcqsTreeNodeConstant;
import cc.rengu.igas.channel.ncqs.common.enums.RespCodeEnum;
import cc.rengu.igas.channel.ncqs.core.model.ChnlBizResponse;
import cc.rengu.igas.channel.ncqs.core.realize.NcqsSeqNoService;
import cc.rengu.igas.channel.ncqs.core.realize.impl.NcqsSeqNoServiceImpl;
import cc.rengu.igas.channel.ncqs.core.service.base.PayService;
import cc.rengu.igas.channel.ncqs.facade.bean.OriTrxInfo;
import cc.rengu.igas.channel.ncqs.facade.request.NcqsRefundAcqRequest;
import cc.rengu.igas.channel.ncqs.facade.response.NcqsRefundAcqResponse;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.DstChannelInfo;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import cc.rengu.utility.base.TimeUtil;
import com.alibaba.fastjson.JSONObject;

import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

/**
 * 退款
 */
public class RefundService extends PayService {

    @Override
    protected Object beforeBizProcess() throws Exception {
        NcqsRefundAcqRequest refundAcqRequest = new NcqsRefundAcqRequest();
        ConvertUtil.convertOutput(refundAcqRequest);
        return refundAcqRequest;
    }

    @Override
    protected ChnlBizResponse callBizService(Object request) throws Exception {
        NcqsRefundAcqRequest refundAcqRequest = (NcqsRefundAcqRequest) request;
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(refundAcqRequest.getHeader().getInstId(),
                NcqsConfigConstant.NCQS_CONF_NODE, NcqsConfigConstant.NCQS_DIRECT_FLAG);
        if (sysParam == null) {
            /*未配置默认间连*/
            return inDirectNcqs(refundAcqRequest);
        } else if (AppParamConstant.YES.equals(sysParam.getParamValue())) {
            return directNcqs(refundAcqRequest);
        } else {
            return inDirectNcqs(refundAcqRequest);
        }

    }

    @Override
    protected void afterBizProcess(ChnlBizResponse response) throws Exception {
        NcqsRefundAcqResponse refundAcqResponse = (NcqsRefundAcqResponse) response.getResult();
        ConvertUtil.convertInput(refundAcqResponse);
    }

    /**
     * 直连银联无卡快捷
     *
     * @param refundAcqRequest
     * @return
     * @throws Exception
     */
    ChnlBizResponse directNcqs(NcqsRefundAcqRequest refundAcqRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        int iReturnCode = 0;
        ChnlBizResponse chnlBizResponse = new ChnlBizResponse();
        NcqsRefundAcqResponse refundAcqResponse = new NcqsRefundAcqResponse();
        String traceNo = refundAcqRequest.getHeader().getTraceNo();
        String instId = refundAcqRequest.getHeader().getInstId();
        DstChannelInfo dstChannelInfo = (DstChannelInfo) xmlTreeUtil.getXmlTreeObjectValue(NcqsTreeNodeConstant.DST_CHANNEL_INFO, DstChannelInfo.class);
        ConvertUtil.convertInput(refundAcqRequest);
        //生成银联无卡快捷平台索引号
        NcqsSeqNoService ncqsSeqNoService = new NcqsSeqNoServiceImpl();
        String ncqsSeqNo = ncqsSeqNoService.genNcqsSeqNo();
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.CHANNEL_SEQ_NUM, ncqsSeqNo);
        //赋值交易时间
        String dateTime;
        if (traceNo == null) {
            dateTime = TimeUtil.getDateTime("yyyyMMddHHmmss");
        } else {
            dateTime = traceNo.substring(8, 22);//日期从流水号截取
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        ParsePosition pos = new ParsePosition(0);
        Date today = dateFormat.parse(dateTime, pos);
        String dateStr = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(today);
        xmlTreeUtil.setXmlTreeStringValue(NcqsTreeNodeConstant.NCQS_TRX_TYP, "1101"); //退款
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, refundAcqRequest.getHeader().getTxnNum());
        xmlTreeUtil.setXmlTreeStringValue(NcqsTreeNodeConstant.NCQS_TRX_AMT, refundAcqRequest.getOrderCcy() + refundAcqRequest.getOrderAmt());

        iReturnCode = schedule.callService(dstChannelInfo.getDstServiceName(), 0);
        if (98 == iReturnCode) {
            rglog.error("调用银联无卡快捷服务<{}>超时，iReturnCode:<{}>", dstChannelInfo.getDstServiceName(), iReturnCode);
            refundAcqResponse.setRespCode("98");
            refundAcqResponse.setRespDesc("交易状态未明");
            chnlBizResponse.setResult(refundAcqResponse);
            return chnlBizResponse;
        } else if (0 != iReturnCode) {
            rglog.error("调用银联无卡快捷服务<{}>失败，iReturnCode:<{}>", dstChannelInfo.getDstServiceName(), iReturnCode);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        }
        ConvertUtil.convertOutput(refundAcqResponse);
        chnlBizResponse.setResult(refundAcqResponse);
        return chnlBizResponse;
    }

    /**
     * 间联cups
     *
     * @param refundAcqRequest
     * @return
     * @throws Exception
     */
    ChnlBizResponse inDirectNcqs(NcqsRefundAcqRequest refundAcqRequest) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        int iReturnCode = 0;
        String algorithm = null;
        ChnlBizResponse chnlBizResponse = new ChnlBizResponse();
        NcqsRefundAcqResponse refundAcqResponse = new NcqsRefundAcqResponse();
        String traceNo = refundAcqRequest.getHeader().getTraceNo();
        String instId = refundAcqRequest.getHeader().getInstId();
        OriTrxInfo oriTrxInfo = refundAcqRequest.getOriTrxInfo();
        if (oriTrxInfo == null || oriTrxInfo.getOriTraceNo() == null) {
            rglog.error("必须上送原请求流水号");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        String oriTraceNo = oriTrxInfo.getOriTraceNo();
        //String oriServiceSn = genServiceSn(instId,oriTraceNo);
        xmlTreeUtil.setXmlTreeStringValue(NcqsTreeNodeConstant.oriServiceSn, oriTraceNo);
        /* 流水号规则：8位渠道标识 + 8位日期 + 6位时间 + 2位数据库服务器集群标识 + 2位预留位 + 6位序号 + 调用序号 */
        /*String transDateTime= traceNo.substring(12,22);
        String cupsSsn = traceNo.substring(26,32);
        String channelSeqNum = genServiceSn(instId,traceNo);*/
        xmlTreeUtil.setXmlTreeStringValue(NcqsTreeNodeConstant.serviceSn, traceNo);
        DstChannelInfo dstChannelInfo = (DstChannelInfo) xmlTreeUtil.getXmlTreeObjectValue(NcqsTreeNodeConstant.DST_CHANNEL_INFO, DstChannelInfo.class);
        ConvertUtil.convertInput(refundAcqRequest);
        xmlTreeUtil.setXmlTreeStringValue(NcqsTreeNodeConstant.NCQS_TRX_AMT, refundAcqRequest.getOrderCcy() + refundAcqRequest.getOrderAmt());

        /*branchId*/
        if (refundAcqRequest.getNcqsReserve() == null) {
            rglog.error("必须上送branchId");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        } else {
            Map<String, Object> reqMap = JSONObject.parseObject(refundAcqRequest.getNcqsReserve());
            for (Map.Entry req : reqMap.entrySet()) {
                xmlTreeUtil.setXmlTreeStringValue((String) req.getKey(), (String) req.getValue());
            }
        }

        xmlTreeUtil.setXmlTreeStringValue(NcqsTreeNodeConstant.REQUESTER_ID, NcqsParamConstant.REQUEST_ID);
        xmlTreeUtil.setXmlTreeStringValue(NcqsTreeNodeConstant.VERSION_ID, NcqsParamConstant.VERSION_ID);
        xmlTreeUtil.setXmlTreeStringValue(NcqsTreeNodeConstant.CHANNEL_ID, NcqsParamConstant.CHANNEL_ID);
        xmlTreeUtil.setXmlTreeStringValue(NcqsTreeNodeConstant.SERVICE_TIME, refundAcqRequest.getHeader().getTransDate() + refundAcqRequest.getHeader().getTransTime());

        xmlTreeUtil.setXmlTreeStringValue(NcqsTreeNodeConstant.serviceId, NcqsParamConstant.REFUND_CDOE);
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, refundAcqRequest.getHeader().getTxnNum());
        iReturnCode = schedule.callService(dstChannelInfo.getDstServiceName(), 0);
        if (98 == iReturnCode) {
            rglog.error("调用银联无卡快捷服务<{}>超时，iReturnCode:<{}>", dstChannelInfo.getDstServiceName(), iReturnCode);
            throw new BizException(RespCodeEnum.TIME_OUT_ERROR.getRespCode(), RespCodeEnum.TIME_OUT_ERROR.getRespDesc());

        } else if (0 != iReturnCode) {
            rglog.error("调用银联全渠道服务<{}>失败，iReturnCode:<{}>", dstChannelInfo.getDstServiceName(), iReturnCode);
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        }

        String esbStatus = xmlTreeUtil.getXmlTreeStringValue(NcqsTreeNodeConstant.ESB_STATUS);
        rglog.info("esbStatus=<{}>", esbStatus);
        if ("COMPLETE".equals(esbStatus)) {
            //ESB成功
            refundAcqResponse.setRespCode(NcqsTreeNodeConstant.SUCCESS_CODE);

            ConvertUtil.convertOutput(refundAcqResponse);
        } else if ("FAIL".equals(esbStatus)) {
            //ESB失败
            refundAcqResponse.setRespCode(xmlTreeUtil.getXmlTreeStringValue(NcqsTreeNodeConstant.ESB_RSP_CODE));
            refundAcqResponse.setRespDesc(xmlTreeUtil.getXmlTreeStringValue(NcqsTreeNodeConstant.ESB_RSP_DESC));
        }

        String trxId = xmlTreeUtil.getXmlTreeStringValue(NcqsTreeNodeConstant.NCQS_TRX_ID);
        refundAcqResponse.setSettleKey(trxId);
        refundAcqResponse.setChannelSeqNum(traceNo);
        if (NcqsParamConstant.NCQS_SUCCESS_CODE.equals(refundAcqResponse.getRespCode())) {
            refundAcqResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            refundAcqResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        }
        chnlBizResponse.setResult(refundAcqResponse);
        return chnlBizResponse;
    }
}
